var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
var events = { exports: {} };
var R = typeof Reflect === "object" ? Reflect : null;
var ReflectApply = R && typeof R.apply === "function" ? R.apply : function ReflectApply2(target, receiver, args) {
  return Function.prototype.apply.call(target, receiver, args);
};
var ReflectOwnKeys;
if (R && typeof R.ownKeys === "function") {
  ReflectOwnKeys = R.ownKeys;
} else if (Object.getOwnPropertySymbols) {
  ReflectOwnKeys = function ReflectOwnKeys2(target) {
    return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
  };
} else {
  ReflectOwnKeys = function ReflectOwnKeys2(target) {
    return Object.getOwnPropertyNames(target);
  };
}
function ProcessEmitWarning(warning) {
  if (console && console.warn)
    console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN2(value) {
  return value !== value;
};
function EventEmitter() {
  EventEmitter.init.call(this);
}
events.exports = EventEmitter;
events.exports.once = once2;
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = void 0;
EventEmitter.prototype._eventsCount = 0;
EventEmitter.prototype._maxListeners = void 0;
var defaultMaxListeners = 10;
function checkListener(listener) {
  if (typeof listener !== "function") {
    throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  }
}
Object.defineProperty(EventEmitter, "defaultMaxListeners", {
  enumerable: true,
  get: function() {
    return defaultMaxListeners;
  },
  set: function(arg) {
    if (typeof arg !== "number" || arg < 0 || NumberIsNaN(arg)) {
      throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + ".");
    }
    defaultMaxListeners = arg;
  }
});
EventEmitter.init = function() {
  if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) {
    this._events = /* @__PURE__ */ Object.create(null);
    this._eventsCount = 0;
  }
  this._maxListeners = this._maxListeners || void 0;
};
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) {
    throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + ".");
  }
  this._maxListeners = n;
  return this;
};
function _getMaxListeners(that) {
  if (that._maxListeners === void 0)
    return EventEmitter.defaultMaxListeners;
  return that._maxListeners;
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  return _getMaxListeners(this);
};
EventEmitter.prototype.emit = function emit(type) {
  var args = [];
  for (var i = 1; i < arguments.length; i++)
    args.push(arguments[i]);
  var doError = type === "error";
  var events2 = this._events;
  if (events2 !== void 0)
    doError = doError && events2.error === void 0;
  else if (!doError)
    return false;
  if (doError) {
    var er;
    if (args.length > 0)
      er = args[0];
    if (er instanceof Error) {
      throw er;
    }
    var err = new Error("Unhandled error." + (er ? " (" + er.message + ")" : ""));
    err.context = er;
    throw err;
  }
  var handler = events2[type];
  if (handler === void 0)
    return false;
  if (typeof handler === "function") {
    ReflectApply(handler, this, args);
  } else {
    var len = handler.length;
    var listeners2 = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      ReflectApply(listeners2[i], this, args);
  }
  return true;
};
function _addListener(target, type, listener, prepend) {
  var m;
  var events2;
  var existing;
  checkListener(listener);
  events2 = target._events;
  if (events2 === void 0) {
    events2 = target._events = /* @__PURE__ */ Object.create(null);
    target._eventsCount = 0;
  } else {
    if (events2.newListener !== void 0) {
      target.emit(
        "newListener",
        type,
        listener.listener ? listener.listener : listener
      );
      events2 = target._events;
    }
    existing = events2[type];
  }
  if (existing === void 0) {
    existing = events2[type] = listener;
    ++target._eventsCount;
  } else {
    if (typeof existing === "function") {
      existing = events2[type] = prepend ? [listener, existing] : [existing, listener];
    } else if (prepend) {
      existing.unshift(listener);
    } else {
      existing.push(listener);
    }
    m = _getMaxListeners(target);
    if (m > 0 && existing.length > m && !existing.warned) {
      existing.warned = true;
      var w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type) + " listeners added. Use emitter.setMaxListeners() to increase limit");
      w.name = "MaxListenersExceededWarning";
      w.emitter = target;
      w.type = type;
      w.count = existing.length;
      ProcessEmitWarning(w);
    }
  }
  return target;
}
EventEmitter.prototype.addListener = function addListener(type, listener) {
  return _addListener(this, type, listener, false);
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.prependListener = function prependListener(type, listener) {
  return _addListener(this, type, listener, true);
};
function onceWrapper() {
  if (!this.fired) {
    this.target.removeListener(this.type, this.wrapFn);
    this.fired = true;
    if (arguments.length === 0)
      return this.listener.call(this.target);
    return this.listener.apply(this.target, arguments);
  }
}
function _onceWrap(target, type, listener) {
  var state = { fired: false, wrapFn: void 0, target, type, listener };
  var wrapped = onceWrapper.bind(state);
  wrapped.listener = listener;
  state.wrapFn = wrapped;
  return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
  checkListener(listener);
  this.on(type, _onceWrap(this, type, listener));
  return this;
};
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) {
  checkListener(listener);
  this.prependListener(type, _onceWrap(this, type, listener));
  return this;
};
EventEmitter.prototype.removeListener = function removeListener(type, listener) {
  var list, events2, position, i, originalListener;
  checkListener(listener);
  events2 = this._events;
  if (events2 === void 0)
    return this;
  list = events2[type];
  if (list === void 0)
    return this;
  if (list === listener || list.listener === listener) {
    if (--this._eventsCount === 0)
      this._events = /* @__PURE__ */ Object.create(null);
    else {
      delete events2[type];
      if (events2.removeListener)
        this.emit("removeListener", type, list.listener || listener);
    }
  } else if (typeof list !== "function") {
    position = -1;
    for (i = list.length - 1; i >= 0; i--) {
      if (list[i] === listener || list[i].listener === listener) {
        originalListener = list[i].listener;
        position = i;
        break;
      }
    }
    if (position < 0)
      return this;
    if (position === 0)
      list.shift();
    else {
      spliceOne(list, position);
    }
    if (list.length === 1)
      events2[type] = list[0];
    if (events2.removeListener !== void 0)
      this.emit("removeListener", type, originalListener || listener);
  }
  return this;
};
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) {
  var listeners2, events2, i;
  events2 = this._events;
  if (events2 === void 0)
    return this;
  if (events2.removeListener === void 0) {
    if (arguments.length === 0) {
      this._events = /* @__PURE__ */ Object.create(null);
      this._eventsCount = 0;
    } else if (events2[type] !== void 0) {
      if (--this._eventsCount === 0)
        this._events = /* @__PURE__ */ Object.create(null);
      else
        delete events2[type];
    }
    return this;
  }
  if (arguments.length === 0) {
    var keys = Object.keys(events2);
    var key;
    for (i = 0; i < keys.length; ++i) {
      key = keys[i];
      if (key === "removeListener")
        continue;
      this.removeAllListeners(key);
    }
    this.removeAllListeners("removeListener");
    this._events = /* @__PURE__ */ Object.create(null);
    this._eventsCount = 0;
    return this;
  }
  listeners2 = events2[type];
  if (typeof listeners2 === "function") {
    this.removeListener(type, listeners2);
  } else if (listeners2 !== void 0) {
    for (i = listeners2.length - 1; i >= 0; i--) {
      this.removeListener(type, listeners2[i]);
    }
  }
  return this;
};
function _listeners(target, type, unwrap) {
  var events2 = target._events;
  if (events2 === void 0)
    return [];
  var evlistener = events2[type];
  if (evlistener === void 0)
    return [];
  if (typeof evlistener === "function")
    return unwrap ? [evlistener.listener || evlistener] : [evlistener];
  return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}
EventEmitter.prototype.listeners = function listeners(type) {
  return _listeners(this, type, true);
};
EventEmitter.prototype.rawListeners = function rawListeners(type) {
  return _listeners(this, type, false);
};
EventEmitter.listenerCount = function(emitter, type) {
  if (typeof emitter.listenerCount === "function") {
    return emitter.listenerCount(type);
  } else {
    return listenerCount.call(emitter, type);
  }
};
EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
  var events2 = this._events;
  if (events2 !== void 0) {
    var evlistener = events2[type];
    if (typeof evlistener === "function") {
      return 1;
    } else if (evlistener !== void 0) {
      return evlistener.length;
    }
  }
  return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
  return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function arrayClone(arr, n) {
  var copy = new Array(n);
  for (var i = 0; i < n; ++i)
    copy[i] = arr[i];
  return copy;
}
function spliceOne(list, index) {
  for (; index + 1 < list.length; index++)
    list[index] = list[index + 1];
  list.pop();
}
function unwrapListeners(arr) {
  var ret = new Array(arr.length);
  for (var i = 0; i < ret.length; ++i) {
    ret[i] = arr[i].listener || arr[i];
  }
  return ret;
}
function once2(emitter, name) {
  return new Promise(function(resolve, reject) {
    function errorListener(err) {
      emitter.removeListener(name, resolver);
      reject(err);
    }
    function resolver() {
      if (typeof emitter.removeListener === "function") {
        emitter.removeListener("error", errorListener);
      }
      resolve([].slice.call(arguments));
    }
    eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
    if (name !== "error") {
      addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
    }
  });
}
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
  if (typeof emitter.on === "function") {
    eventTargetAgnosticAddListener(emitter, "error", handler, flags);
  }
}
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
  if (typeof emitter.on === "function") {
    if (flags.once) {
      emitter.once(name, listener);
    } else {
      emitter.on(name, listener);
    }
  } else if (typeof emitter.addEventListener === "function") {
    emitter.addEventListener(name, function wrapListener(arg) {
      if (flags.once) {
        emitter.removeEventListener(name, wrapListener);
      }
      listener(arg);
    });
  } else {
    throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
  }
}
class WSocket {
  constructor(url, {
    protocols = void 0,
    reconnectInterval = 2e3,
    maxConnectCount = 5,
    isHeart = true,
    isReconnect = true,
    pingInterval = 5e3,
    pongInterval = 3e3,
    pingMsg = "ping",
    pongMsg = "SUCCESS",
    isErrorStack = false,
    isPongResponse = false
  } = {}) {
    __publicField(this, "url");
    __publicField(this, "protocols");
    __publicField(this, "maxConnectCount");
    __publicField(this, "reconnectInterval");
    __publicField(this, "pingInterval");
    __publicField(this, "pongInterval");
    __publicField(this, "isHeart");
    __publicField(this, "isPongResponse");
    __publicField(this, "isReconnect");
    __publicField(this, "pingMsg");
    __publicField(this, "pongMsg");
    __publicField(this, "isErrorStack");
    __publicField(this, "ws", null);
    __publicField(this, "isReconnectLoading", false);
    __publicField(this, "timeId");
    __publicField(this, "isCustomClose", false);
    __publicField(this, "errorStack", []);
    __publicField(this, "eventCenter", new events.exports.EventEmitter());
    __publicField(this, "curConnectCount", 0);
    __publicField(this, "isDestroy", false);
    __publicField(this, "pingId");
    __publicField(this, "pongId");
    this.url = url;
    this.protocols = protocols;
    this.reconnectInterval = reconnectInterval;
    this.maxConnectCount = maxConnectCount;
    this.isHeart = isHeart;
    this.isReconnect = isReconnect;
    this.pingInterval = pingInterval;
    this.pongInterval = pongInterval;
    this.pingMsg = pingMsg;
    this.pongMsg = pongMsg;
    this.isErrorStack = isErrorStack;
    this.isPongResponse = isPongResponse;
    this._create();
  }
  _create() {
    if ("WebSocket" in window) {
      this.ws = new WebSocket(this.url, this.protocols);
      this._onopen();
      this._onerror();
      this._onclose();
      this._onmessage();
    } else {
      console.log("\u4F60\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 WebSocket");
    }
  }
  _onopen() {
    this.ws.onopen = (evt) => {
      this.emit("ws-open", evt);
      console.log(`ws onopen: ${this.url}`, evt, this);
      this._startHeart();
      this._sendErrorStack();
      this.errorStack = [];
      this.curConnectCount = 0;
      this.isReconnectLoading = false;
    };
  }
  _onerror() {
    this.ws.onerror = (evt) => {
      this.emit("ws-error", evt);
      console.log("ws onerror: ", evt, this);
      this.reconnect();
    };
  }
  _onclose() {
    this.ws.onclose = (evt) => {
      this.emit("ws-close", evt);
      console.log(`ws onclose: ${this.url}`, evt, this);
      if (this.isCustomClose)
        return;
      this.reconnect();
    };
  }
  _onmessage() {
    this.ws.onmessage = (event) => {
      this.emit("ws-message", event);
      if (this.isPongResponse) {
        this._resetHeart();
        if (event.data === this.pongMsg) {
          return;
        }
      }
      this.emit("message", event.data);
    };
  }
  _sendErrorStack() {
    if (this.isErrorStack) {
      this.errorStack.forEach((message) => {
        message && this.send(message);
      });
    }
  }
  _startHeart() {
    if (this.isHeart) {
      if (this.isPongResponse) {
        this.pingId = setTimeout(() => {
          if (this.ws.readyState === 1) {
            this.send(this.pingMsg);
            this.pongId = setTimeout(() => {
              this.reconnect();
            }, this.pongInterval);
          }
        }, this.pingInterval);
      } else {
        this.pingId = setInterval(() => {
          if (this.ws.readyState === 1) {
            this.send(this.pingMsg);
          }
        }, this.pingInterval);
      }
    }
  }
  _closeHeart() {
    this.isPongResponse ? clearTimeout(this.pingId) : clearInterval(this.pingId);
    clearTimeout(this.pongId);
    this.pingId = void 0;
    this.pongId = void 0;
  }
  _resetHeart() {
    this._closeHeart();
    this._startHeart();
  }
  reconnect() {
    this.emit("reconnect");
    if (!this.isReconnect)
      return;
    if (this.isDestroy)
      return;
    if (this.isReconnectLoading)
      return;
    if (this.curConnectCount >= this.maxConnectCount)
      return;
    this.isReconnectLoading = true;
    this.curConnectCount++;
    clearTimeout(this.timeId);
    this._closeHeart();
    this.ws.close();
    this.timeId = setTimeout(() => {
      this._create();
      this.isReconnectLoading = false;
    }, this.reconnectInterval);
  }
  send(message) {
    this.emit("send", message);
    if (this.isErrorStack && this.ws.readyState !== 1) {
      this.errorStack.push(message);
      return;
    }
    this.ws.send(message);
  }
  close() {
    this.emit("close");
    this.isCustomClose = true;
    this._closeHeart();
    this.ws && this.ws.close();
  }
  start() {
    this.emit("start");
    this.isCustomClose = false;
    this.reconnect();
  }
  on(eventName, cb) {
    this.eventCenter.on(eventName, cb);
  }
  off(eventName, cb) {
    this.eventCenter.off(eventName, cb);
  }
  emit(eventName, ...args) {
    this.eventCenter.emit(eventName, ...args);
  }
  destroy() {
    try {
      this.emit("destroy");
      this.isDestroy = true;
      clearTimeout(this.timeId);
      this.close();
      this.ws = null;
      this.errorStack = [];
      this.eventCenter.removeAllListeners();
      this.curConnectCount = 0;
    } catch (err) {
      console.log("destroy err: ", err);
    }
  }
}
export { WSocket, WSocket as default };
